package cts

import compound.repository.entries.Compound
import edu.ucdavis.genomics.metabolomics.binbase.connector.references.sdf.InchFinder
import edu.ucdavis.genomics.metabolomics.binbase.connector.references.sdf.SDFContentResolver
import util.CompoundHelper
import edu.ucdavis.genomics.metabolomics.binbase.connector.references.sdf.SdfToInchi
import org.apache.tools.ant.filters.StringInputStream
import org.apache.log4j.Logger
import org.codehaus.groovy.grails.commons.ApplicationHolder
import compound.repository.entries.DBLinks
import edu.ucdavis.genomics.metabolomics.exception.BinBaseException
import types.GenerateDomainClassStatement
import util.DomainClassUtil

/**
 * used to upload data and modify database content
 */
class UploadService {

    static transactional = true

    static expose = ['cxf']

    /**
     * uplodas a molfile
     * and returns the id of the uploaded compound
     * @param molFile
     * @return
     */
    long uploadMolFile(String molFile) {

        UploadSDFFinder finder = new UploadSDFFinder()
        SdfToInchi.sdfToInchi(new StringInputStream(molFile), finder)

        Compound compound = finder.compound

        log.info("uploaded mol: ${compound.inchi}")
        return compound.id
    }

    /**
     * registers some metadata
     * @param compoundId - id
     * @param key - which metadata
     * @param value - value
     */
    void registerMetaData(long compoundId, String key, String value) {
        def validKeys = DomainClassUtil.getInstance().validKeys
        def validClasses = DomainClassUtil.getInstance().validClasses

        if (validKeys.contains(key) == false) {
            log.warn "invalid key (${key}) was used and so rejected"
            throw new BinBaseException("sorry you need to provide a valid metadata key!")
        }
        else {

            Compound compound = Compound.get(compoundId)

            if (compound == null) {
                log.warn "invalid compound id (${compoundId}) was used and so rejected"

                throw new BinBaseException("sorry the compound(${compoundId}) was not found!")
            }

            log.info "query for ${key} and ${value}"

            //prepare our link object
            DBLinks l = validClasses.get(key).newInstance()
            l.compound = compound
            l.linkID = value
            l.sourceName = key

            //check if this already exists
            def result = DBLinks.findAllBySourceNameAndLinkID(l.getSourceName(), value)

            if (result.size() == 0) {

                try {
                    l.populate()
                    l.save()
                    compound.save(flush: true)

                    log.info "assigned new dblink ${l} for ${compound}"
                }
                catch (Exception e) {
                    log.warn(e.getMessage(), e)
                    throw e
                }
            }
            else {
                log.info("sorry this dblink already exists -> ignore")
            }
        }

    }

    /**
     * returns the metadata keys for this service
     * @return
     */
    String[] listMetaDataKey() {

        def validKeys = DomainClassUtil.getInstance().validKeys

        String[] array = new String[validKeys.size()]
        validKeys.eachWithIndex {String value, int counter ->
            array[counter] = value
        }

        return array
    }
}

class UploadSDFFinder implements InchFinder {

    Logger log = Logger.getLogger(getClass())

    Compound compound

    void foundInchi(String s, Map<Object, Object> objectObjectMap) {
        SDFContentResolver resolver = new SDFContentResolver()
        resolver.prepare(objectObjectMap)
        compound = CompoundHelper.getCompound(resolver.getInchi(), resolver.getInchiKey(), log)

        CompoundHelper.saveCompound compound, log

    }


}